/*
-----------------------------------------------------------------------------
This source file is part of Labor3D
(Labor 3D Graphics Engine)

Copyright (c) 2009-2020 Rock Mao
* creator : Rock Mao
* created : 2009-5-18   14:35
* filename: LaborD3D10GPUProgram.h
-----------------------------------------------------------------------------
*/

#ifndef __LABORD3D10GPUPROGRAM_H__
#define __LABORD3D10GPUPROGRAM_H__
#include "LaborCoreDef.h"
#include "Renderer\LaborGPUProgram.h"
#include "LaborD3D10ShaderParameters.h"
#include "LaborD3D10VertexShader.h"
#include "LaborD3D10PixelShader.h"
#include "LaborD3D10GeometryShader.h"
NAMESPACE_LABOR3D_BEGIN

class CLD3D10RenderSystem;
class CLD3D10GpuProgramParameters : public ILGpuProgramParameters
{
public:
	CLD3D10ShaderParameters* m_pVSParameters;
	CLD3D10ShaderParameters* m_pPSParameters;
	CLD3D10ShaderParameters* m_pGSParameters;
	ILGpuProgram*          m_pGpuProgram;
public:
	virtual ~CLD3D10GpuProgramParameters();
	CLD3D10GpuProgramParameters(ILGpuProgram* pGpuProgram);
	ILGpuProgram*           getGpuProgram();
	ILShaderParameters*     getShaderParamTab(eLShaderType shType);
	bool                    updateRenderContext();
	bool                    commit();

	bool                   setTexture(const wchar_t* name        , ILaborTexture* pTexture , eLShaderType _shader =  el_ST_None);
	bool                   setTexture(const int texName          , ILaborTexture* pTexture , eLShaderType _shader =  el_ST_None);
	bool                   setTextureBySlot(const int iSlot      , ILaborTexture* pTexture , eLShaderType _shader =  el_ST_None);

	CLD3D10ShaderParameters*  getShaderParamTable(eLShaderType shType);
	bool                   setParamater(const wchar_t* name , float  _value ,       eLShaderType shType = el_ST_None);
	bool                   setParamater(const wchar_t* name , int    _value ,       eLShaderType shType = el_ST_None);
	bool                   setParamater(const wchar_t* name , CLPoint4& _value ,    eLShaderType shType = el_ST_None);
	bool                   setParamater(const wchar_t* name , CLMatrix4x4& _value , eLShaderType shType = el_ST_None);

	bool                   setParamater(const wchar_t* name , CLPoint4* _array ,    int n , int baseIndex = 0 , eLShaderType shType = el_ST_None);
	bool                   setParamater(const wchar_t* name , int*   _array ,       int n , int baseIndex = 0 , eLShaderType shType = el_ST_None);
	bool                   setParamater(const wchar_t* name , float* _array ,       int n , int baseIndex = 0 , eLShaderType shType = el_ST_None);
	bool                   setParamater(const wchar_t* name , CLMatrix4x4* _array , int n , int baseIndex = 0 , eLShaderType shType = el_ST_None);

public:

	template <typename T> bool T_setParamater(const wchar_t* name , T  _value , eLShaderType _shader)
	{
		if(_shader == el_ST_None)
		{
			if(m_pPSParameters && m_pPSParameters->setParamater(name , _value ) )
				return true;
			if(m_pVSParameters && m_pVSParameters->setParamater(name , _value) )
				return true;
			if(m_pGSParameters && m_pGSParameters->setParamater(name , _value) )
				return true;
			return false;
		}
		else
		{
			CLD3D10ShaderParameters* pTable = getShaderParamTable(_shader);
			if(pTable == NULL) return false;
			pTable->setParamater(name , _value);
			return true;
		}
		return false;
	}

	template <typename T> bool T_setParamater(const wchar_t* name , T* _array , int n , int baseIndex , eLShaderType _shader)
	{
		if(_shader == el_ST_None)
		{
			if(m_pPSParameters && m_pPSParameters->setParamater(name , _array , n , baseIndex) )
				return true;
			if(m_pVSParameters && m_pVSParameters->setParamater(name , _array , n , baseIndex) )
				return true;
			if(m_pGSParameters && m_pGSParameters->setParamater(name , _array , n , baseIndex) )
				return true;
			return false;
		}
		else
		{
			CLD3D10ShaderParameters* pTable = getShaderParamTable(_shader);
			if(pTable == NULL) return false;
			pTable->setParamater(name , _array , n , baseIndex);
			return true;
		}
		return false;
	}


};

class CLD3D10GPUProgram : public ILGpuProgram
{
	friend class CLD3D10RenderSystem;
	CLD3D10GeometryShader*         m_pGeometryShader;
	CLD3D10PixelShader*            m_pPixelShader;
	CLD3D10VertexShader*           m_pVertexShader;
	CLD3D10GpuProgramParameters*   m_defParamTable;
	ILGpuProgramParameters*        m_pInstalledTable;

public:
	bool                    _afterLoad();
public:
	CLD3D10GPUProgram();
	~CLD3D10GPUProgram();
	bool                    load(const wchar_t* vsName , const wchar_t* psName, const wchar_t* gsName , unsigned long arg);
	bool                    isLoaded();
	bool                    unload();
	unsigned long           memUsage(){return 1 ; };

	bool                    setTexture(const wchar_t* textureName , ILaborTexture* pTexture , eLShaderType _shader =  el_ST_None);
	bool                    setTexture(const int texName          , ILaborTexture* pTexture , eLShaderType _shader =  el_ST_None);
	bool                    setTextureBySlot(const int iSlot      , ILaborTexture* pTexture , eLShaderType _shader =  el_ST_None);

	ILGpuProgramParameters*  getParamTable(){ return m_pInstalledTable ? m_pInstalledTable : m_defParamTable ; }
	void                     setParamTable(ILGpuProgramParameters* pTable) {m_pInstalledTable = pTable ; }
	ILGpuProgramParameters*  createParamTable(bool bLoadDef);
	ILGpuProgramParameters*  getDefaultParamTable();
	void                     commit();
	virtual bool             setParamater(const wchar_t* name , CLMatrix4x4& _value , eLShaderType shType = el_ST_None);

};


NAMESPACE_LABOR3D_END

#endif // __LABORD3D10GPUPROGRAM_H__